MODULE = PlPN          PACKAGE = PlPN::PN

#
# Pod::Html is kind of brain-dead:
#
# Place Z<> between function names and parentheses, otherwise Pod::Html
# assumes you meant to put C<...> around it
#
# Put explicit text in all links L<use my text, stupid|some::perl::module>,
# otherwise Pod::Html assumes you want "the X manpage". (Does not apply to
# relative links withing this file.)
#
# It also assumes you want a link if you have C<...> with text matching a
# potential link target. The only way I've found around that is to split it
# up into multiple pieces: C<wo>C<rd>. Looks correct in the resulting HTML,
# but it's ugly to have <code>wo</code><code>rd</code> in the source, and I
# shouldn't have to do it.
#

=head1 NAME

PlPN::PN - The Programmer's Notepad object

=head1 SYNOPSIS

	use PlPN qw(PN);
	
	PN->GetCurrentDocument;
	PN->GetGlobalOutputWindow;
	
	# etc.

=head1 DESCRIPTION

Allows access to Programmer's Notepad functions from Perl.

=head1 METHODS

=over

=cut

void
DESTROY(THIS)
		extensions::IPN* THIS;
	CODE:
		// empty our menu and doc trackers
		// (in case we're cycling the interpreter instead of exiting)
		g_menu_tracker.Blank();
		g_document_tracker.Blank();

# we only want the == operator
FALLBACK: FALSE

bool
eq(a,b,swap)
		extensions::IPN* a;
		extensions::IPN* b;
		IV swap;
	OVERLOAD: ==
	CODE:
		RETVAL = (a == b);
	OUTPUT:
		RETVAL

=item GetIFaceVersionZ<>()

Gets the version of the Programmer's Notepad interface implemented by the
PlPN plugin.

=cut

unsigned int
extensions::IPN::GetIFaceVersion()

=item GetVersionZ<>()

Gets the version of the Programmer's Notepad executable.

=cut

const char*
extensions::IPN::GetVersion()

=item AddEventSinkZ<>($sink)

=item RemoveEventSinkZ<>($sink)

Adds or removes a L<PlPN::AppEventSink|PlPN::AppEventSink>. You only need this if you're
writing your own event sink, you don't need it if you're using the default
event sink via L<PlPN::RegisterEvent|PlPN/RegisterEvent|PlPN::RegisterEvent|PlPN/RegisterEvent>.

=cut

void
extensions::IPN::AddEventSink(sink)
		SV* sink;
	CODE:
		g_app_event_sink->AttachPerlSink(sink);

void
extensions::IPN::RemoveEventSink(sink)
		SV* sink;
	CODE:
		g_app_event_sink->DetachPerlSink(sink);

=item GetScriptRegistryZ<>()

Gets the L<PlPN::ScriptRegistry|PlPN::ScriptRegistry>, which allows you to register script
runners. You only need this if you're writing your own script runner, you
don't need it if you're using the default runner via
L<PlPN::RegisterScript|PlPN/RegisterScript|PlPN::RegisterScript|PlPN/RegisterScript>.

=cut

extensions::IScriptRegistry*
extensions::IPN::GetScriptRegistry()
		const char* CLASS = "PlPN::ScriptRegistry";

=item GetOptionsManagerZ<>()

Gets the L<PlPN::Options|PlPN::Options> object, which allows access to Programmer's
Notepad settings, and also allows you to create your own settings.

=cut

extensions::IOptions*
extensions::IPN::GetOptionsManager()
		const char* CLASS = "PlPN::Options";

=item GetCurrentDocumentZ<>()

Gets the L<PlPN::Document|PlPN::Document> object representing the currently active
document.

=cut

SV*
extensions::IPN::GetCurrentDocument()
	CODE:
		if (g_document_tracker.Count() == 0)
			XSRETURN_UNDEF;
		extensions::IDocumentPtr doc = THIS->GetCurrentDocument();
		TrackedDocument* tdoc = g_document_tracker.Fetch(doc);
		// if for some reason we're not already added
		if (tdoc == NULL) {
			g_document_tracker.Add(doc, &tdoc);
		}
		RETVAL = tdoc->perl_doc;
		SvREFCNT_inc(RETVAL);
	OUTPUT:
		RETVAL

=item GetGlobalOutputWindowZ<>()

Gets the L<PlPN::TextOutput|PlPN::TextOutput> object, which represents the
main output window. As of this writing, the extensions interface does not
allow access to the individual output window associated with a document.

=cut

extensions::ITextOutput*
extensions::IPN::GetGlobalOutputWindow()
		const char* CLASS = "PlPN::TextOutput";

=item GetMainWindowZ<>()

Gets the handle for the main Programmer's Notepad window. This is probably
not much use in ordinary Perl scripts, but if you use a GUI package (such as
L<Win32::GUI|Win32::GUI>), you might want this value.

=cut

HWND
extensions::IPN::GetMainWindow()

=item GetUserSearchOptionsZ<>()

Gets the user search options, a L<PlPN::SearchOptions|PlPN::SearchOptions> object

See also L<PlPN::Options::GetSearchOptions|PlPN::Options/GetSearchOptions>.

=cut

extensions::ISearchOptions*
extensions::IPN::GetUserSearchOptions()
		const char* CLASS = "PlPN::SearchOptions";

=item FindInFilesZ<>($options)

Performs a search using the values from C<$options>, a
L<PlPN::SearchOptions|PlPN::SearchOptions> object. Note that it does not return anything; the
matches are displayed via Programmer's Notepad.

=cut

void
extensions::IPN::FindInFiles(options)
		extensions::ISearchOptions* options;

=item InputBoxZ<>($title, $caption)

Displays a message requesting user input, and returns that user input.
Returns C<undef> if the user cancels, a string otherwise.

=cut

wchar_t*
extensions::IPN::InputBox(title, caption)
		const wchar_t* title;
		const wchar_t* caption;
	CLEANUP:
		// caller responsible for freeing memory after utf8_2_wide
		free((void*)title);
		free((void*)caption);
		// strings from PN must be released via ReleaseString
		my_pn->ReleaseString(RETVAL);

=item NewDocumentZ<>($scheme = undef)

Creates a new empty document using the given scheme, or the default scheme
if scheme is not defined. Returns the associated
L<PlPN::Document|PlPN::Document> object.

=cut

SV*
extensions::IPN::NewDocument(scheme = NULL)
		const char* scheme;
	CODE:
		extensions::IDocumentPtr doc = THIS->NewDocument(scheme);
		TrackedDocument* tdoc = g_document_tracker.Fetch(doc);
		if (tdoc == NULL) {
			g_document_tracker.Add(doc, &tdoc);
		}
		RETVAL = tdoc->perl_doc;
		//SvREFCNT_inc(RETVAL);
	OUTPUT:
		RETVAL

=item OpenDocumentZ<>($filepath, scheme = undef)

Opens a the given file using the given scheme, or the default scheme if no
scheme is not defined. Returns the associated L<PlPN::Document|PlPN::Document>
object.

=cut

SV*
extensions::IPN::OpenDocument(filepath, scheme)
		const wchar_t* filepath;
		const char* scheme;
	CODE:
		extensions::IDocumentPtr doc = THIS->OpenDocument(filepath, scheme);
		TrackedDocument* tdoc = g_document_tracker.Fetch(doc);
		RETVAL = tdoc->perl_doc;
	OUTPUT:
		RETVAL
	CLEANUP:
		// caller responsible for freeing memory after utf8_2_wide
		free((void*)filepath);

#=item AddTagSourceZ<>($tagSource)
#
#Don't use this. The current version of the extensions interface does not
#provide a TagSource object, so that object is unimplemented in Perl
#
#=cut
#
#void
#extensions::IPN::AddTagSource(tagSource)
#		extensions::ITagSource* tagSource;

=item AddPluginMenuItemsZ<>($menu)

Adds C<$menu>, a L<PlPN::Menu|PlPN::Menu> object, to the C<Extensions> menu in
Programmer's Notepad.

The extensions interface has no functionality to remove a menu.

=cut

void
extensions::IPN::AddPluginMenuItems(menu)
		PerlMenu* menu;
	CODE:
		if (g_menu_tracker.Add(menu))
			THIS->AddPluginMenuItems((extensions::IMenuItems*)menu);

=item AddRecorderZ<>($recorder)

=item RemoveRecorderZ<>($recorder)

Sets C<$recorder>, a L<PlPN::Recorder|PlPN::Recorder> object, to receive
macro recording events. Currently Programmer's Notepad only supports one
recorder object at a time. The Perl implementation is a little more
flexible: the single C++ object will propagate the events to any number of
Perl objects.

Unfortunately, if another extension calls the C++ version of
C<Add>C<Recorder>, PlPN's recorder will no longer be active. You can,
however, call C<Add>C<Recorder> multiple times on the same Perl recorder; if
the recorder has already been added, it will not be added a second time, but
the C++ recorder will be activated again so that the associated Perl
recorder(s) will receive events.

The extensions interface has no functionality to remove a recorder.
Therefore, C<Remove>C<Recorder> will only remove the Perl recorder; it will
not unset the C++ recorder.

=cut

void
extensions::IPN::AddRecorder(recorder)
		SV* recorder;
	CODE:
		// since PN only allows one (C++) recorder, we make sure our
		// recorder is set every time a Perl recorder is added
		g_recorder->AttachPerlSink(recorder);
		my_pn->AddRecorder(g_recorder);

void
RemoveRecorder(THIS, recorder)
		extensions::IPN* THIS;
		SV* recorder;
	CODE:
		g_recorder->DetachPerlSink(recorder);

=back

=head1 COPYRIGHT and LICENCE

Copyright (c) 2012 Sean Healy. All rights reserved.

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=cut
